package gu.simplemq;

import java.lang.reflect.Type;
import java.util.Map;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;

import gu.simplemq.json.BaseJsonEncoder;

import static com.google.common.base.Preconditions.*;

public class MessageQueueFactorys implements Constant{

	private static volatile IMessageQueueFactory defaultFactory = null;
	private MessageQueueFactorys() {
	}
	/**
	 * 设置默认{@link IMessageQueueFactory}实例<br>
	 * 仅当默认实例未初始化(为{@code null})且输入参数不为{@code null}时有效(返回{@code true})
	 * 如果默认实例已经初始化,则输出警告日志,返回{@code false}
	 * @param defaultFactory 为{@code null}返回{@code false}
	 * @return  设置成功返回{@code true},否则返回{@code false}
	 */
	public static boolean setDefaultFactory(IMessageQueueFactory defaultFactory){
		if(MessageQueueFactorys.defaultFactory == null){
			synchronized (MessageQueueFactorys.class) {
				if(MessageQueueFactorys.defaultFactory == null){
					if(defaultFactory != null){
						checkArgument(defaultFactory.initialized(),"input defaultFactory is uninitialized");
						MessageQueueFactorys.defaultFactory = defaultFactory;
						return true;
					}else {
						logger.warn("input argument 'defaultFactory' is null");
						return false;
					}
				}
			}
		}
		logger.warn("INVALID INVOCATION,default factory was initialized already before this invocation");
		return false;
	}
	/**
	 * 返回默认实例,如果 {@link #defaultFactory}为null则抛出异常
	 * @return {@link IMessageQueueFactory}实例
	 * @throws NullPointerException 默认实例未初始化
	 */
	public static IMessageQueueFactory getDefaultFactory() {		
		return checkNotNull(defaultFactory,"defaultFactory is uninitialized");
	}
	/**
	 * 检测默认实例是否初始化
	 * @return 默认实例已经初始化则返回{@code true},否则返回false
	 */
	public static boolean defaultFactoryInitialized(){
		return defaultFactory != null;
	}
	public static ImmutableMap<MessageQueueType, IMessageQueueFactory> getFactories(){
		checkState(MQContextLoader.factories.size() > 0,"NOT FOUND instance of %s" ,IMessageQueueFactory.class.getName());
		return MQContextLoader.factories;
	}
	public static IMessageQueueFactory getFactory(String implType){
		return getFactory(MessageQueueType.valueOf(implType));
	}
	public static IMessageQueueFactory getFactory(MessageQueueType implType){
		return checkNotNull(getFactories().get(implType),
				"INVALID impltype,INVALID VALUES:%s",Joiner.on(".").join(getFactories().keySet()));
	}
	public static Map<String,Object> asMQConnParam(String json){
		@SuppressWarnings("serial")
		Type paramType = new TypeToken<Map<String, Object>>(){}.getType();
		return BaseJsonEncoder.getEncoder().fromJson(json, paramType);
	}
	public static Map<String,String> asMQConnParam2(String json){
		@SuppressWarnings("serial")
		Type paramType = new TypeToken<Map<String, String>>(){}.getType();
		return BaseJsonEncoder.getEncoder().fromJson(json, paramType);
	}
	/**
	 * 关闭所有消息系统(message queue)工厂接口实例
	 */
	public static void closeAllFactories(){
		for(IMessageQueueFactory factory:getFactories().values()){
			try {
				factory.close();
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}
}
